//
//  STRegex.swift
//  iOSProjectExtensionSwift
//
//  Created by Apple on 2020/1/13.
//  Copyright © 2020 lidianchao. All rights reserved.
//

import Foundation
///////////////////////////// 正则表达式相关  ///////////////////////////////
extension String {
    func isValidateWithRegex(regex:String) -> Bool {
        let pre = NSPredicate(format: "SELF MATCHES \(regex)");
        return pre.evaluate(with: self);
    }
    /* 邮箱验证 MODIFIED BY HELENSONG */
    func isValidEmail() ->Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
        let emailTest = NSPredicate(format: "SELF MATCHES %@",emailRegex);
        return emailTest.evaluate(with: self);
    }
    /* 手机号码验证 MODIFIED BY HELENSONG */
    func isValidPhoneNum () ->Bool{
        let phoneRegex = "^(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[0-9])[0-9]{8}$";
        let phoneTest = NSPredicate(format: "SELF MATCHES %@",phoneRegex);
        return phoneTest.evaluate(with: self);
    }
    /* 车牌号验证 MODIFIED BY HELENSONG */
    func isValidCarNo () ->Bool{
        let carRegex = "^[A-Za-z]{1}[A-Za-z_0-9]{5}$";
        let carTest = NSPredicate(format: "SELF MATCHES %@",carRegex);
        return carTest.evaluate(with: self);
    }
    /** 网址验证 */
    func isValidUrl () ->Bool{
        let regex = "^((http)|(https))+:[^\\s]+\\.[^\\s]*$";
        return isValidateWithRegex(regex: regex);
    }

    /** 邮政编码 */
    func isValidPostalcode () ->Bool{
        let phoneRegex = "^[0-8]\\d{5}(?!\\d)$";
        let phoneTest = NSPredicate(format: "SELF MATCHES %@",phoneRegex);
        return phoneTest.evaluate(with: self);
    }
    
    func isValidIP() -> Bool {
        let regex = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
        let pre = NSPredicate(format: "SELF MATCHES %@",regex);
        let rc = pre.evaluate(with: self);
        if rc {
            let componds = self.components(separatedBy: ",");
            
            var v = true;
            for s: String in componds {
                if Int(s)! > 255 {
                    v = false;
                    break;
                }
            }
            return v
        }
        return false;
    }
    /** 身份证验证 refer to http://blog.csdn.net/afyzgh/article/details/16965107 */
    func isValidIdCardNum() -> Bool {
        var value = self;
        value = value.replacingOccurrences(of: "X", with: "x");
        value = value.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines);
        var length = 0;
        if value.isEmpty {
            return false;
        }
        length = value.count;
        if (length != 15 && length != 18) {
            return false;
        }
        // 省份代码
        let areasArray = ["11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", "81", "82", "91"];
        let valueStart2 = String(value.prefix(2));
        var areaFlag = false;
        for areaCode: String in areasArray {
            if areaCode==valueStart2 {
                areaFlag = true;
                break;
            }
        }
        if !areaFlag {
            return false;
        }
        
        var regularExpression = NSRegularExpression();
        var numberofMatch = 0;
        var year = 0;
        
        switch length {
        case 15:
            year = Int((value as NSString).substring(with: NSRange(location: 6, length: 2)))!+1900;
            if(year % 4 == 0 || (year % 100 == 0 && year % 4 == 0)) {
                do {
                    regularExpression = try NSRegularExpression.init(pattern: "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$", options: NSRegularExpression.Options.caseInsensitive);// 测试出生日期的合法性
                }catch { }
            }
            else {
                do {
                    regularExpression = try NSRegularExpression.init(pattern: "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$", options: NSRegularExpression.Options.caseInsensitive);
                } catch {}
            }
            numberofMatch = regularExpression.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange(location: 0, length: value.count));
            if numberofMatch > 0 {
                return true;
            }
            return false;
        case 18:
            year = Int((value as NSString).substring(with: NSRange(location: 6, length: 6)))!
            if(year % 4 == 0 || (year % 100 == 0 && year % 4 == 0)) {
                do {
                    regularExpression = try NSRegularExpression.init(pattern: "^[1-9][0-9]{5}19|20[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$", options: NSRegularExpression.Options.caseInsensitive);// 测试出生日期的合法性
                }catch { }
            }
            else {
                do {
                    regularExpression = try NSRegularExpression.init(pattern: "^[1-9][0-9]{5}19|20[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$", options: NSRegularExpression.Options.caseInsensitive);
                } catch {}
            }
            numberofMatch = regularExpression.numberOfMatches(in: value, options: NSRegularExpression.MatchingOptions.reportProgress, range: NSRange(location: 0, length: value.count));
            if numberofMatch > 0 {
                let S = (Int((value as NSString).substring(with: NSRange(location: 0, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 10, length: 1)))!) * 7 +
                (Int((value as NSString).substring(with: NSRange(location: 1, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 11, length: 1)))!) * 9 +
                (Int((value as NSString).substring(with: NSRange(location: 2, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 12, length: 1)))!) * 10 +
                (Int((value as NSString).substring(with: NSRange(location: 3, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 13, length: 1)))!) * 5 +
                (Int((value as NSString).substring(with: NSRange(location: 4, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 14, length: 1)))!) * 8 +
                (Int((value as NSString).substring(with: NSRange(location: 5, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 15, length: 1)))!) * 4 +
                (Int((value as NSString).substring(with: NSRange(location: 6, length: 1)))! + Int((value as NSString).substring(with: NSRange(location: 16, length: 1)))!) * 2 +
                Int((value as NSString).substring(with: NSRange(location: 7, length: 1)))! * 1 +
                Int((value as NSString).substring(with: NSRange(location: 8, length: 1)))! * 6 +
                Int((value as NSString).substring(with: NSRange(location: 9, length: 1)))! * 3
                let Y = S % 11;
                var M = "F";
                let JYM = "10X98765432";
                M = (JYM as NSString).substring(with: NSRange(location: Y, length: 1));// 判断校验位
                if (M == (value as NSString).substring(with: NSRange(location: 17, length: 1)).uppercased()) {
                    return true;// 检测ID的校验位
                }
                return false;
            }
            return false;
        default:
            return false;
        }
    }
    /// 身份证验证  是否符合最小长度、最长长度，是否包含中文,数字，字母，其他字符，首字母是否可以为数字
    /// - Parameters:
    ///   - minLenth:  账号最小长度
    ///   - maxLenth: 账号最长长度
    ///   - containChinese: 是否包含中文
    ///   - containDigtal: 包含数字
    ///   - containLetter: 包含字母
    ///   - containOtherCharacter: 其他字符
    ///   - firstCannotBeDigtal: 首字母不能为数字
    func isValidWithMinLenth(minLenth:Int, maxLenth:Int, containChinese:Bool, containDigtal:Bool, containLetter:Bool, containOtherCharacter:String, firstCannotBeDigtal:Bool) -> Bool {
        var rc = true;
        if firstCannotBeDigtal {
            let regex = "^[0-9]+.*";
            let pre = NSPredicate(format: "SELF MATCHES %@",regex);
            rc = pre.evaluate(with: self);
            if rc {
                return false;
            }
        }
        let hanzi = containChinese ? "[\u{4e00}-\u{9fa5}]+" : "";
        let digtalRegex = containDigtal ? "0-9" : "";
        let containOtherCharacterRegex = containOtherCharacter.isEmpty ? "" : containOtherCharacter
        let characterRegex = String.init(format: "[%@A-Za-z%@%@]",  hanzi, digtalRegex, containOtherCharacterRegex);
        let regex = String.init(format: "%@{%@,%@}", characterRegex, String(minLenth), String(maxLenth));
        let pre = NSPredicate(format: "SELF MATCHES %@", regex)
        return pre.evaluate(with: self);
    }
    /** 去掉两端空格和换行符 */
    func stringByTrimmingBlank () -> String {
        return self.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines);
    }
    /** 工商税号 */
    func isValidTaxNo() -> Bool {
        let emailRegex = "[0-9]\\d{13}([0-9]|X)$";
        let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
        return emailTest.evaluate(with: self);
    }
    //base64编码
    func toBase64() -> String? {
        if let data = self.data(using: .utf8) {
            return data.base64EncodedString()
        }
        return nil
    }
    //base64解码
    func fromBase64() -> String? {
        if let data = Data(base64Encoded: self) {
            return String(data: data, encoding: .utf8)
        }
        return nil
    }
}
